package uap.bs.prealert.engine;

import java.io.Serializable;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Collection;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.mutable.MutableObject;

import nc.bs.framework.common.NCLocator;
import nc.bs.framework.server.LiveServerAgent;
import nc.bs.framework.server.ServerInstance;
import nc.bs.logging.Logger;
import nc.bs.ml.NCLangResOnserver;
import nc.bs.pub.pa.PaUtils;
import nc.bs.pub.pa.PreAlertObject;
import nc.bs.pub.pa.PreAlertReturnType;
import nc.vo.ml.NCLangRes4VoTransl;
import ncc.task.quartz.dao.entity.ScheduleJob;
import nccloud.bs.pub.pa.ScheduleJobManager;
import uap.bs.prealert.engine.executor.INCCPreAlertConfirmCall;
import uap.itf.prealert.engine.ExecutionLogger;
import uap.itf.prealert.engine.ExecutionLoggerFactory;
import uap.itf.prealert.engine.MessageConstructor;
import uap.itf.prealert.engine.MessageConstructorFactory;
import uap.itf.prealert.engine.MessagePersister;
import uap.itf.prealert.engine.MessagePersisterFactory;
import uap.itf.prealert.engine.MessageSender;
import uap.itf.prealert.engine.MessageSenderFactory;
import uap.vo.prealert.engine.EngineContext;
import uap.vo.prealert.engine.SendMethod;
import uap.vo.prealert.util.PreAlertUtil;

public class NCCPreAlertConfirmCallImpl
  implements INCCPreAlertConfirmCall
{
  public void successCall(Map<String, Serializable> paramMap)
  {
    Logger.init("prealert");

    PreAlertObject result = (PreAlertObject)paramMap.get("result");
    EngineContext context = (EngineContext)paramMap.get("context");
    long beginMillis = ((Long)paramMap.get("beginMillis")).longValue();

    String log = "";
    ExecutionLogger logger = ((ExecutionLoggerFactory)NCLocator.getInstance().lookup(ExecutionLoggerFactory.class)).getLogger(context);
    SendMethod[] receivertype = context.getReceiverContext().getSendMethods();
    ScheduleJob job = null;
    String taskId = "";
    try
    {
      if ((result != null) && (result.getReturnType() != PreAlertReturnType.RETURNNOTHING)) {
        if (result.getReturnObj() == null) {
          String errorMsg = generateErrorMsgOfNullReturnObj(context, result);
          context.appendLogString(errorMsg);
        }
        else
        {
          MessageConstructor constructor = ((MessageConstructorFactory)NCLocator.getInstance().lookup(MessageConstructorFactory.class))
            .getMessageConstructor(context, result);

          Collection messages = constructor.construct(context, result);

          if (PreAlertUtil.isNotEmpty(messages))
          {
            MessagePersister persister = ((MessagePersisterFactory)NCLocator.getInstance().lookup(MessagePersisterFactory.class))
              .getMessagePersister(context, messages);

            persister.persist(context, messages);

            MessageSender sender = ((MessageSenderFactory)NCLocator.getInstance().lookup(MessageSenderFactory.class))
              .getMessageSender(context, messages);

            sender.sendMessages(context, messages);
          }
        }
      } else if (((result == null) || (result.getReturnType() == PreAlertReturnType.RETURNNOTHING)) && (receivertype.length > 0))
      {
        log = NCLangRes4VoTransl.getNCLangRes().getStrByID("101502", "EngineImplDelegator-0001");
      }

      if ((StringUtils.isEmpty(log)) && (context.getExecutorContext() != null)) {
    	  log = context.getExecutorContext().getLogString();
    	  
    	  if(log == null) log = "";
      }
        
      
      logger.log(context, beginMillis, true, log);
    } catch (Exception e) {
      logger.log(context, beginMillis, false, PaUtils.getStack(e));
    }
    finally {
      updateJobStatus(context.getAlertRegistry().getPrimaryKey(), beginMillis);
    }
    Logger.init(Logger.getModule());
  }

  public void failCall(Map<String, Serializable> paramMap)
  {
    Logger.init("prealert");

    EngineContext context = (EngineContext)paramMap.get("context");
    long beginMillis = ((Long)paramMap.get("beginMillis")).longValue();

    String gtxId = (String)paramMap.get("saga_gtxid");

    gtxId = "Remote call failed:" + gtxId;

    ExecutionLogger logger = ((ExecutionLoggerFactory)NCLocator.getInstance().lookup(ExecutionLoggerFactory.class)).getLogger(context);
    logger.log(context, beginMillis, false, gtxId);
    String taskId = context.getAlertRegistry().getPrimaryKey();

    updateJobStatus(taskId, beginMillis);
    Logger.init(Logger.getModule());
  }

  public void updateJobStatus(String taskId, long beginMillis)
  {
    if ((taskId == null) || (taskId.isEmpty())) {
      return;
    }
    ScheduleJob job = ScheduleJobManager.getInstance().queryScheduleJobByTaskId(taskId);
    if (job == null) {
      return;
    }
    if (job.getScheExecTime().longValue() == -2L) {
      ScheduleJobManager.getInstance().deleteScheduleJobByTaskId(job.getTaskId());
      return;
    }

    job.setTaskStatus(Integer.valueOf(1));
    job.setRunCount(Integer.valueOf(job.getRunCount().intValue() + 1));
    job.setAvgExecTime(Long.valueOf(System.currentTimeMillis() - beginMillis));

    ServerInstance localhost = ((LiveServerAgent)NCLocator.getInstance().lookup(LiveServerAgent.class))
      .getServerInstance();
    job.setExecServerName(localhost.getName());
    job.setExecServerAddress(localhost.getAddress());
    job.setExecServerInstanceid(localhost.getInstanceId());
    ScheduleJobManager.getInstance().updateScheduleJob(job);
  }

  public static String getServiceName()
  {
    String serviceName = null;
    InetAddress addr = null;
    try {
      addr = InetAddress.getLocalHost();
      serviceName = addr.getHostName().toString();
    } catch (UnknownHostException e) {
      return "nccServer";
    }
    return serviceName;
  }

  private String generateErrorMsgOfNullReturnObj(EngineContext context, PreAlertObject result)
  {
    MutableObject msgHolder = new MutableObject();
    PreAlertUtil.doInDefaultLangBs(new Runnable() {
		
		@Override
		public void run()
		  {
		    StringBuffer sb = new StringBuffer();

		    sb.append(NCLangResOnserver.getInstance().getStrByID("prealertres", "RegistryAddEntity-000000"));

		    sb.append(", pk=");
		    sb.append(context.getAlertRegistry().getPrimaryKey());
		    sb.append(", pk_alerttype=");
		    sb.append(context.getAlertRegistry().getPk_alerttype());
		    sb.append(", busi_plugin=");
		    sb.append(context.getAlertType().getBusi_plugin());
		    sb.append(NCLangResOnserver.getInstance().getStrByID("prealertres", "EngineImplDelegator-0000"));

		    sb.append(result.getReturnType().toString());
		    sb.append(NCLangResOnserver.getInstance().getStrByID("prealertres", "EngineImplDelegator-0001"));

		    msgHolder.setValue(sb.toString());
		  }
	});

    return (String)msgHolder.getValue();
  }

  private ExecutionLogger getNCLogLogger(Throwable e) {
    return new ExecutionLogger() {
		
		@Override
		public void log(EngineContext context, long begin, boolean succeeded, String log)
		  {
		    StringBuffer sb = new StringBuffer();
		    sb.append("execution loging failure: " + e.getMessage());
		    sb.append("\n");
		    sb.append("execution detail: ");
		    sb.append("pk_alerttype=" + context.getAlertType().getPrimaryKey());
		    sb.append("pk_registry=" + context.getAlertRegistry().getPrimaryKey());
		    sb.append(", beginMills=" + begin);
		    sb.append(", succeeded=" + succeeded);
		    sb.append(", originLogString=" + log);

		    Logger.error(sb.toString(), e);
		  }
	};
  }
}